package com.guinea.core.web;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import org.apache.commons.digester.Digester;
import org.apache.struts.Globals;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.config.FormBeanConfig;
import org.apache.struts.config.ModuleConfig;
import org.apache.struts.config.ModuleConfigFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.guinea.core.SpringContextHolder;

public class MyActionServlet extends ActionServlet {
	
    /**
     * <p>Initialize the module configuration information for the
     * specified module.</p>
     *
     * @param prefix Module prefix for this module
     * @param paths Comma-separated list of context-relative resource path(s)
     *  for this modules's configuration resource(s)
     *
     * @exception ServletException if initialization cannot be performed
     * @since Struts 1.1
     */
    protected ModuleConfig initModuleConfig(String prefix, String paths)
        throws ServletException {

        // :FIXME: Document UnavailableException? (Doesn't actually throw anything)

        if (log.isDebugEnabled()) {
            log.debug(
                "Initializing module path '"
                    + prefix
                    + "' configuration from '"
                    + paths
                    + "'");
        }

        // Parse the configuration for this module
        ModuleConfigFactory factoryObject = ModuleConfigFactory.createFactory();
        ModuleConfig config = factoryObject.createModuleConfig(prefix);

        // Configure the Digester instance we will use
        Digester digester = initConfigDigester();

        // Process each specified resource path
        while (paths.length() > 0) {
            //digester.push(config);
            String path = null;
            int comma = paths.indexOf(',');
            if (comma >= 0) {
                path = paths.substring(0, comma).trim();
                paths = paths.substring(comma + 1);
            } else {
                path = paths.trim();
                paths = "";
            }

            if (path.length() < 1) {
                break;
            }

            this.parseModuleConfigFile(digester, path, config);
        }

        getServletContext().setAttribute(
            Globals.MODULE_KEY + config.getPrefix(),
            config);

        // Force creation and registration of DynaActionFormClass instances
        // for all dynamic form beans we wil be using
        FormBeanConfig fbs[] = config.findFormBeanConfigs();
        for (int i = 0; i < fbs.length; i++) {
            if (fbs[i].getDynamic()) {
                fbs[i].getDynaActionFormClass();
            }
        }

        return config;
    }
	/**
	 * <p>
	 * Parses one module config file.
	 * </p>
	 * 
	 * @param digester
	 *            Digester instance that does the parsing
	 * @param path
	 *            The path to the config file to parse.
	 * 
	 * @throws UnavailableException
	 *             if file cannot be read or parsed
	 * @since Struts 1.2
	 */
	protected void parseModuleConfigFile(Digester digester, String path, ModuleConfig config)
			throws UnavailableException {
		try {
			URL url;
			if (path
					.startsWith(ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX)) {
				ResourcePatternResolver resolver = ResourcePatternUtils
						.getResourcePatternResolver(SpringContextHolder
								.getApplicationContext());
				Resource[] rules = resolver.getResources(path);
				for (int i = 0; i < rules.length; i++) {
					Resource r = rules[i];
					url = r.getURL();
					parseModuleConfigFile(digester, path, url, config);
				}
			} else {
				url = getServletContext().getResource(path);
				// If the config isn't in the servlet context, try the class
				// loader
				// which allows the config files to be stored in a jar
				if (url == null) {
					url = getClass().getResource(path);
				}
				parseModuleConfigFile(digester, path, url, config);
			}

		} catch (MalformedURLException e) {
			handleConfigException(path, e);
		} catch (IOException e) {
			handleConfigException(path, e);
		}
	}

	protected void parseModuleConfigFile(Digester digester, String path, URL url, ModuleConfig config)
			throws UnavailableException {
		digester.push(config);
		InputStream input = null;
		try {
			if (url == null) {
				String msg = internal.getMessage("configMissing", path);
				log.error(msg);
				throw new UnavailableException(msg);
			}

			InputSource is = new InputSource(url.toExternalForm());
			input = url.openStream();
			is.setByteStream(input);
			digester.parse(is);

		} catch (MalformedURLException e) {
			handleConfigException(path, e);
		} catch (IOException e) {
			handleConfigException(path, e);
		} catch (SAXException e) {
			handleConfigException(path, e);
		} finally {
			if (input != null) {
				try {
					input.close();
				} catch (IOException e) {
					throw new UnavailableException(e.getMessage());
				}
			}
		}
	}

	/**
	 * <p>
	 * Simplifies exception handling in the <code>parseModuleConfigFile</code>
	 * method.
	 * <p>
	 * 
	 * @param path
	 * @param e
	 * @throws UnavailableException
	 *             as a wrapper around Exception
	 */
	private void handleConfigException(String path, Exception e)
			throws UnavailableException {

		String msg = internal.getMessage("configParse", path);
		log.error(msg, e);
		throw new UnavailableException(msg);
	}
}
